﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml;

namespace Update
{
    public partial class Form1 : Form
    {
        WebClient web = new WebClient();
        private List<string> paths = new List<string>();
        private string IP;
        private string ServerPath;
        private string Port;
        private string LoginClient;
        private string UpdateClient;
        public Form1()
        {
            InitializeComponent();
            xml();
            getFilename();
            if (paths.Count > 0)
            {
                MessageBox.Show("发现新版本,开始更新！");
                Thread thread = new Thread(updatefile);
                thread.Start();
            }
        }

        //更新文件
        public void updatefile()
        {
            string path = Environment.CurrentDirectory;
            path = path.Replace("\\", "/");
            for (int i = 0; i < paths.Count; i++)
            {
                string url = IP + Port + ServerPath + paths[i];
                string local = path + paths[i];
                string[] filename = paths[i].ToString().Split('/');
                string[] newfilename = new string[filename.Length - 1];
                for (int j = 0; j < filename.Length - 1; j++)
                {
                    newfilename[j] = filename[j];
                }
                string bb = string.Join("/", newfilename);
                if (!Directory.Exists(path + bb))
                {
                    Directory.CreateDirectory(path + bb);
                }
                web.DownloadFile(url, local);
                SetTextMesssage(i + 1, paths.Count, local);
            }
            MessageBox.Show("已更新完毕!");
            Process.Start(LoginClient + ".exe");
            killProcess(UpdateClient);
        }

        //下载服务端md5配置文件并对比本地配置文件 获取需要更新的文件路径
        public void getFilename()
        {
            string Versions = IP + Port + ServerPath + "/Versions.txt";
            string[] oldVersions = File.ReadAllLines(Environment.CurrentDirectory + "\\Versions.txt");
            List<string> newVersions = Get1(Versions);
            if (oldVersions[0] != newVersions[0])
            {
                killProcess(LoginClient);
                Thread.Sleep(1000);
                string MD5url = IP + Port + ServerPath + "/MD5.txt";
                List<string> oldLines = getmd5();
                List<string> newLines = Get1(MD5url);
                string[,] oldmd5 = new string[oldLines.Count, 2];
                string[,] newmd5 = new string[newLines.Count, 2];

                for (int k = 0; k < newLines.Count; k++)
                {
                    string[] newlies = newLines[k].Split(',');

                    for (int j = 0; j < 2; j++)
                    {
                        newmd5[k, j] = newlies[j].ToString();
                    }
                    for (int i = 0; i < oldLines.Count; i++)
                    {
                        if (k == 0)
                        {
                            string[] oldlies = oldLines[i].Split(',');
                            for (int j = 0; j < 2; j++)
                            {
                                oldmd5[i, j] = oldlies[j].ToString();
                            }
                        }

                        if (newmd5[k, 0] == oldmd5[i, 0])
                        {
                            if (newmd5[k, 1] == oldmd5[i, 1])
                            {
                                newmd5[k, 0] = null;
                                newmd5[k, 1] = null;
                            }
                        }
                    }
                    if (newmd5[k, 0] != null && newmd5[k, 0] != "")
                    {
                        paths.Add(newmd5[k, 0]);
                    }
                }
                Write(newVersions[0], Environment.CurrentDirectory + "\\Versions.txt");
                if (paths.Count == 0)
                {
                    Process.Start(LoginClient + ".exe");
                    killProcess(UpdateClient);
                }
            }
            else
            {
                killProcess(UpdateClient);
            }
        }

        //更改控件显示
        delegate void SetPos(int ipos, int num, string text);//代理

        private void SetTextMesssage(int ipos, int num, string text)
        {
            int a = ipos * 100 / num;
            if (InvokeRequired)
            {
                SetPos setpos = new SetPos(SetTextMesssage);
                Invoke(setpos, new object[] { ipos, num, text });
            }
            else
            {
                label1.Text = string.Format("已完成文件下载{0}%  {1}/{2}(文件个数)", a, ipos.ToString(), num);
                progressBar1.Value = Convert.ToInt32(a);
                textBox1.AppendText(text + "\r\n");
            }
        }
        //杀死进程
        private void killProcess(string a)
        {
            try
            {
                Process[] p = Process.GetProcessesByName(a);
                p[0].Kill();
            }
            catch (System.Exception) { MessageBox.Show("杀进程错误"); }
        }
        //读取xml文件
        public void xml()
        {
            XmlDocument doc = new XmlDocument();
            doc.Load(@"UpdateServerConfig.xml");

            XmlNode xn = doc.SelectSingleNode("ServerConfig");
            XmlNodeList xnl = xn.ChildNodes;
            foreach (XmlElement xn1 in xnl)
            {
                XmlElement xe = (XmlElement)xn1;
                XmlNodeList xe10 = xe.ChildNodes;
                IP = xe10.Item(0).InnerText;
                ServerPath = xe10.Item(2).InnerText;
                Port = xe10.Item(1).InnerText;
                LoginClient = xe10.Item(3).InnerText;
                UpdateClient = xe10.Item(4).InnerText;
            }
        }
        //生成路径与md5
        public List<string> getmd5()
        {
            List<string> a = new List<string>();
            string[] files = Directory.GetFiles(Environment.CurrentDirectory, "*", SearchOption.AllDirectories);
            for (int i = 0; i < files.Length; i++)
            {
                string filePath = files[i];
                string relativePath = filePath.Replace(Environment.CurrentDirectory, "").Replace("\\", "/");
                if (!filePath.Contains("Versions.txt") && !filePath.Contains("Update.exe"))
                {
                    string md5="";
                    try { md5 = getFileHash(filePath); }
                    catch (Exception e) { MessageBox.Show(e.Message); }
                    
                    a.Add(relativePath + "," + md5);
                }
            }
            return a;
        }
        //获取md5值
        public static string getFileHash(string filePath)
        {

            try
            {
                string fileMD5 = "";
                FileStream fs = new FileStream(filePath, FileMode.Open);
                int len = (int)fs.Length;
                byte[] data = new byte[len];
                fs.Read(data, 0, len);
                fs.Close();
                MD5 md5 = new MD5CryptoServiceProvider();
                byte[] result = md5.ComputeHash(data);

                foreach (byte b in result)
                {
                    fileMD5 += Convert.ToString(b, 16);
                }
                return fileMD5;
            }
            catch (FileNotFoundException e)
            {
                return "";
            }
        }
        //读取服务端文件
        private List<string> Get1(string strURL)
        {
            List<string> responseText = new List<string>();
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(strURL);
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            StreamReader myreader = new StreamReader(response.GetResponseStream(), Encoding.UTF8);

            string lineText;
            while ((lineText = myreader.ReadLine()) != null)
            {
                responseText.Add(lineText);
            }
            myreader.Close();
            return responseText;
        }
        //写文件
        public void Write(string md5, string path)
        {
            FileStream fs = new FileStream(path, FileMode.Create);
            StreamWriter sw = new StreamWriter(fs);
            //开始写入
            sw.Write(md5);
            //清空缓冲区
            sw.Flush();
            //关闭流
            sw.Close();
            fs.Close();
        }
    }
}
